package com.yanqu.road.server.manager.activity.snowgarden;

import com.yanqu.road.dao.impl.player.CrossActivityMallDayBuyDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.CrossActivityMallDayBuyData;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.pb.activity.ServerMallBuyProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.sync.message.SyncResponse;
import com.yanqu.road.utils.date.DateHelper;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public class CrossMallDayBuyActivity {
    private int activityId;
    //key:day
    private Map<Integer, CrossMallBuyDayInfo> dayInfoMap = new ConcurrentHashMap<>();

    private Set<Long> needSyncServerIdSet = new HashSet<>();

    public CrossMallDayBuyActivity(int activityId) {
        this.activityId = activityId;
        loadDb();
    }

    private void loadDb() {
        Map<Integer, CrossMallBuyDayInfo> tempDayInfoMap = new ConcurrentHashMap<>();

        List<CrossActivityMallDayBuyData> tempList = new CrossActivityMallDayBuyDaoImpl().getCrossActivityMallDayBuyDataList(activityId);
        for (CrossActivityMallDayBuyData dayBuyData : tempList) {
            CrossMallBuyDayInfo crossMallBuyDayInfo = tempDayInfoMap.get(dayBuyData.getDay());
            if (crossMallBuyDayInfo == null) {
                crossMallBuyDayInfo = new CrossMallBuyDayInfo(activityId, dayBuyData.getDay());
                tempDayInfoMap.put(dayBuyData.getDay(), crossMallBuyDayInfo);
            }
            crossMallBuyDayInfo.addMallDayBuyData(dayBuyData);
        }

        dayInfoMap = tempDayInfoMap;
    }

    public int getActivityId() {
        return activityId;
    }

    private CrossActivityMallDayBuyData initDayBuyData(int day, int mallId) {
        CrossMallBuyDayInfo crossMallBuyDayInfo = dayInfoMap.get(day);
        if (crossMallBuyDayInfo == null) {
            synchronized (dayInfoMap) {
                crossMallBuyDayInfo = dayInfoMap.get(day);
                if (crossMallBuyDayInfo == null) {
                    crossMallBuyDayInfo = new CrossMallBuyDayInfo(activityId, day);
                    dayInfoMap.put(day, crossMallBuyDayInfo);
                }
            }
        }
        CrossActivityMallDayBuyData buyData = crossMallBuyDayInfo.initDayBuyData(mallId);
        return buyData;
    }

    public void updateServerMallBuy(long serverId, int day, int mallId, long count) {
        CrossMallBuyDayInfo crossMallBuyDayInfo = dayInfoMap.get(day);
        if (crossMallBuyDayInfo == null) {
            synchronized (dayInfoMap) {
                crossMallBuyDayInfo = dayInfoMap.get(day);
                if (crossMallBuyDayInfo == null) {
                    crossMallBuyDayInfo = new CrossMallBuyDayInfo(activityId, day);
                    dayInfoMap.put(day, crossMallBuyDayInfo);
                }
            }
        }
        crossMallBuyDayInfo.updateServerMallBuy(serverId, mallId, count);

        ActivityInfo activityInfo = ActivityMgr.getActivityInfo(activityId);
        if (activityInfo != null) {
            synchronized (needSyncServerIdSet) {
                needSyncServerIdSet.addAll(activityInfo.getServerIdList());
            }
        }
    }

    public void syncServerMallBuyToGameServer() {
        if (needSyncServerIdSet.isEmpty()) {
            return;
        }

        List<Long> serverIds = new ArrayList<>();
        synchronized (needSyncServerIdSet) {
            serverIds.addAll(needSyncServerIdSet);
            needSyncServerIdSet.clear();
        }

        List<ServerMallBuyProto.DayBuyDataTemp> dayBuyDataTemps = parseDayBuyDataTempList(getBuyDataList());
        ServerMallBuyProto.CrossMallBuyToServerSyncMsg.Builder syncMsg = ServerMallBuyProto.CrossMallBuyToServerSyncMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        syncMsg.addAllCrossBuyData(dayBuyDataTemps);

        for (Long serverId : serverIds) {
            CompletableFuture<SyncResponse> future = MessageHelper.sendToGameServer(serverId, GameProtocol.S_SERVER_BUY_COUNT_REFRESH, activityId, 0, syncMsg, null);
            future.thenAccept(syncResponse -> {
                if (syncResponse.getErrorCode() != 0) {
                    CrossActivityMallDayBuyMgr.getLogger().error("CrossMallDayBuyActivity syncServerMallBuyToGameServer error, serverId:{}, errorCode:{}", serverId, syncResponse.getErrorCode());
                    addNeedSyncServerId(serverId);
                }
            });
        }
    }

    public List<CrossActivityMallDayBuyData> getBuyDataList() {
        List<CrossActivityMallDayBuyData> list = new ArrayList<>();
        List<CrossMallBuyDayInfo> dayInfoList = new ArrayList<>();
        synchronized (dayInfoMap) {
            dayInfoList.addAll(dayInfoMap.values());
        }

        for (CrossMallBuyDayInfo dayInfo : dayInfoList) {
            list.addAll(dayInfo.getBuyDataList());
        }
        return list;
    }

    public List<ServerMallBuyProto.DayBuyDataTemp> parseDayBuyDataTempList(List<CrossActivityMallDayBuyData> buyDataList) {
        List<ServerMallBuyProto.DayBuyDataTemp> list = new ArrayList<>();
        for (CrossActivityMallDayBuyData buyData : buyDataList) {
            ServerMallBuyProto.DayBuyDataTemp.Builder builder = ServerMallBuyProto.DayBuyDataTemp.newBuilder();
            builder.setDay(buyData.getDay());
            builder.setMallId(buyData.getMallId());
            builder.setNewCount(buyData.getTotalBuyCount());
            list.add(builder.build());
        }
        return list;
    }

    public void addNeedSyncServerId(long serverId) {
        synchronized (needSyncServerIdSet) {
            needSyncServerIdSet.add(serverId);
        }
    }

    /**
     * 检查每日补发的任务
     */
    public void checkDayAutoRewardTask() {
        //每天的0点-0点5分不补发,等待数据同步
        long todayZeroTimeStamp = DateHelper.getTodayZeroTimeStamp();
        long afterCheckTime = todayZeroTimeStamp + 5 * DateHelper.MINUTE_MILLIONS;
        long currentTime = DateHelper.getCurrentTime();
        if (currentTime < afterCheckTime) {
            return;
        }

        ActivityInfo activityInfo = ActivityMgr.getActivityInfo(activityId);
        if (activityInfo == null) {
            return;
        }
        int day = ActivityHelper.getWhichDayAfterBeginTime(activityInfo);

        List<CrossActivityMallDayBuyData> needNotifyDataList = new ArrayList<>();

        List<CrossActivityMallDayBuyData> buyDataList = getBuyDataList();
        for (CrossActivityMallDayBuyData buyData : buyDataList) {
            if (!buyData.getServerIdList().isEmpty()) {//已经在补发中
                needNotifyDataList.add(buyData);
                continue;
            }

            if (buyData.getDay() < day) {
                if (buyData.getStatus() == 0) {//设置进入补发状态
                    buyData.setStatus(1);
                    buyData.setServerIdList(activityInfo.getServerIdList());
                    needNotifyDataList.add(buyData);
                } else if (buyData.getStatus() == 1) {
                    //到这里说明所有服都通知过了
                    buyData.setStatus(2);
                }
            }
        }

        //区服需要同步的数据
        Map<Long, List<CrossActivityMallDayBuyData>> serverIdBuyDataMap = new HashMap<>();
        for (CrossActivityMallDayBuyData dayBuyData : needNotifyDataList) {
            List<Long> filterList = new ArrayList<>();
            boolean isFilter = false;
            for (Long serverId : dayBuyData.getServerIdList()) {
                if (serverId == null) {
                    isFilter = true;
                    continue;
                }
                filterList.add(serverId);
                List<CrossActivityMallDayBuyData> buyDataListTemp = serverIdBuyDataMap.get(serverId);
                if (buyDataListTemp == null) {
                    buyDataListTemp = new ArrayList<>();
                    serverIdBuyDataMap.put(serverId, buyDataListTemp);
                }
                buyDataListTemp.add(dayBuyData);
            }
            if (isFilter) {
                dayBuyData.setServerIdList(filterList);
            }
        }

        for (Map.Entry<Long, List<CrossActivityMallDayBuyData>> entry : serverIdBuyDataMap.entrySet()) {
            Long serverId = entry.getKey();
            List<ServerMallBuyProto.DayBuyDataTemp> dayBuyDataTemps = parseDayBuyDataTempList(entry.getValue());
            ServerMallBuyProto.CrossMallBuyToServerSyncMsg.Builder syncMsg = ServerMallBuyProto.CrossMallBuyToServerSyncMsg.newBuilder();
            syncMsg.setActivityId(activityId);
            syncMsg.addAllCrossBuyData(dayBuyDataTemps);

            CompletableFuture<SyncResponse> future = MessageHelper.sendToGameServer(serverId, GameProtocol.S_SERVER_BUY_DAY_AUTO_REWARD_NOTIFY, activityId, 0, syncMsg, null);
            future.thenAccept(syncResponse -> {
                if (syncResponse.getErrorCode() == 0) {
                    for (ServerMallBuyProto.DayBuyDataTemp buyDataTemp : syncMsg.getCrossBuyDataList()) {
                        CrossActivityMallDayBuyData buyData = getBuyDataOnlyGet(buyDataTemp.getDay(), buyDataTemp.getMallId());
                        if (buyData != null) {//确认游戏服接收到了
                            buyData.removeServerId(serverId);
                        }
                    }
                }
            });
        }

    }

    public CrossActivityMallDayBuyData getBuyDataOnlyGet(int day, int mallId) {
        CrossMallBuyDayInfo mallBuyDayInfo = dayInfoMap.get(day);
        if (mallBuyDayInfo == null) {
            return null;
        }
        CrossActivityMallDayBuyData mallBuyData = mallBuyDayInfo.getMallBuyData(mallId);
        if (mallBuyData == null) {
            return null;
        }
        return mallBuyData;
    }


    public void save() {
        List<CrossActivityMallDayBuyData> buyDataList = getBuyDataList();

        for (CrossActivityMallDayBuyData buyData : buyDataList) {
            if (buyData.isInsertOption()) {
                new CrossActivityMallDayBuyDaoImpl().add(buyData);
            } else if (buyData.isUpdateOption()) {
                new CrossActivityMallDayBuyDaoImpl().update(buyData);
            }
        }
    }

    public List<CrossActivityMallDayBuyData> getBuyDataListByDay(int day) {
        List<CrossActivityMallDayBuyData> list = new ArrayList<>();
        CrossMallBuyDayInfo crossMallBuyDayInfo = dayInfoMap.get(day);
        if (crossMallBuyDayInfo == null) {
            return list;
        }
        list.addAll(crossMallBuyDayInfo.getBuyDataList());
        return list;
    }

    /**
     * 假进度操作
     */
    public void checkFakeBuyTask() {
        SnowGardenFakeBuyConfig buyConfig = CrossActivityMallDayBuyConfigMgr.getSnowGardenFakeBuyConfig(activityId);
        if (buyConfig == null) {
            CrossActivityMallDayBuyMgr.getLogger().info("checkFakeBuyTask buyConfig is null activityId={}", activityId);
            ActivityInfo activityInfo = ActivityMgr.getActivityInfo(activityId);
            if (activityInfo != null) {
                buyConfig = CrossActivityMallDayBuyConfigMgr.reloadConfig(activityInfo);
            }
            if (buyConfig == null) {
                return;
            }
        }
        int day = ActivityHelper.getWhichDayAfterBeginTime(buyConfig.getActivityInfo());
        List<CrossActivityMallDayBuyData> buyDataList = new ArrayList<>();
        Map<Integer, MallInfo> mallInfoMap = buyConfig.getMallInfoMap();
        for (MallInfo mallInfo : mallInfoMap.values()) {
            buyDataList.add(initDayBuyData(day, mallInfo.getMallId()));
        }
        if (mallInfoMap.isEmpty()) {
            CrossActivityMallDayBuyMgr.getLogger().info("checkFakeBuyTask mallInfoMap is empty activityId={}", activityId);
            return;
        }

        if(buyConfig.getActivityInfo().getChildType() == 3){
            //夏日运动会，领奖期不能购买，不需要假进度
            long now = System.currentTimeMillis() / 1000;
            if(now >= buyConfig.getActivityInfo().getEndTime()){
                return;
            }
        }

        boolean isAddFake = false;
        for (CrossActivityMallDayBuyData dayBuyData : buyDataList) {
            int mallId = dayBuyData.getMallId();
            long totalBuyCount = dayBuyData.getTotalBuyCount();
            int targetNum = buyConfig.getTargetNum(mallId);
            int hourNum = buyConfig.calcNowHourNum(mallId);

            if (totalBuyCount >= targetNum) {
                continue;
            }

            if (buyConfig.isNeedAddFakeCount(mallId, dayBuyData.getLastAddFakeTime())) {
                dayBuyData.setLastAddFakeTime(DateHelper.getCurrentTime() / 1000);
                int addFakeBuyCountOnce = buyConfig.getAddFakeBuyCountOnce(mallId, hourNum);
                dayBuyData.setFakeBuyCount(dayBuyData.getFakeBuyCount() + addFakeBuyCountOnce);

                CrossActivityMallDayBuyMgr.getLogger().info("SnowGardenFakeBuyTask add fake buy count, activityId:{}, day:{}, mallId:{}, addFakeBuyCountOnce:{}, totalBuyCount:{}, fakeBuyCount:{}",
                        activityId, day, mallId, addFakeBuyCountOnce, dayBuyData.getTotalBuyCount(), dayBuyData.getFakeBuyCount());

                isAddFake = true;
            }
        }

        if (isAddFake) {
            synchronized (needSyncServerIdSet) {
                needSyncServerIdSet.addAll(buyConfig.getActivityInfo().getServerIdList());
            }
        }
    }

    /**
     * 修复或打印用的接口
     * @param params
     */
    public void repair(String params) {

    }
}
